import React from 'react';
import { Tabs, Tab } from 'react-bootstrap';
import { connect } from 'react-redux';
import WorkflowMetaDraw from "./WorkflowMetaDraw";
import dagreD3 from "dagre-d3";
import d3 from "d3";

function isEmpty(obj) {
  for(var name in obj) {
    return false;
  }
  return true;
};

class WorkflowMetaAdd extends React.Component {

  constructor(props) {
    super(props);
    this.setSvgNode = elem => this.svgElem = elem;
    this.drawNode = this.drawNode.bind(this);
    this.grapher = new dagreD3.render();
    this.updateStartNodeName= this.updateStartNodeName.bind(this);
    this.updateEdges = this.updateEdges.bind(this);
    this.addInsertJoinLine = this.addInsertJoinLine.bind(this);
    this.state = {
        startNodeName:'',
        allNode:{},
        allEdge:[],
    };

    let starPoints = function (outerRadius, innerRadius) {
      var results = "";
      var angle = Math.PI
          / 8;
      for (var i = 0; i < 2 * 8; i++) {
        // Use outer or inner radius depending on what iteration we are in.
        var r = (i & 1) == 0 ? outerRadius : innerRadius;
        var currX = 0 + Math.cos(i * angle) * r;
        var currY = 0 + Math.sin(i * angle) * r;
        if (i == 0) {
          results = currX + "," + currY;
        } else {
          results += ", " + currX + "," + currY;
        }
      }
      return results;
    };

    this.grapher.shapes().house = function (parent, bbox, node) {
      var w = bbox.width,
          h = bbox.height,
          points = [
            {x: 0, y: 0},
            {x: w, y: 0},
            {x: w, y: -h},
            {x: w / 2, y: -h * 3 / 2},
            {x: 0, y: -h}
          ];
      let shapeSvg = parent.insert("polygon", ":first-child")
          .attr("points", points.map(function (d) {
            return d.x + "," + d.y;
          }).join(" "))
          .attr("transform", "translate(" + (-w / 2) + "," + (h * 3 / 4) + ")");

      node.intersect = function (point) {
        return dagreD3.intersect.polygon(node, points, point);
      };

      return shapeSvg;
    };

    this.grapher.shapes().star = function (parent, bbox, node) {
      var w = bbox.width,
          h = bbox.height,
          points = [
            {x: 0, y: 0},
            {x: w, y: 0},
            {x: w, y: -h},
            {x: w / 2, y: -h * 3 / 2},
            {x: 0, y: -h}
          ];
      let shapeSvg = parent.insert("polygon", ":first-child").attr("points", starPoints(w, h))
      node.intersect = function (point) {
        return dagreD3.intersect.polygon(node, points, point);
      };

      return shapeSvg;
    };
  }

  updateStartNodeName(nodeName){
    this.state.startNodeName =nodeName;
  }

  addInsertJoinLine(fromNodeName,toNodeName){
    let defstyle = 'stroke: #ccc; fill: transparent; stroke-dasharray: 5, 5';
    const {allNode,allEdge} = this.state;
    if(fromNodeName == "final"){
      console.log("final不能为from");
      return;
    }
    let have = false;
    allEdge.forEach(e=> {
      if(e.from ==fromNodeName && e.to ==toNodeName){
          have = true;
          console.log("已经存在line了");
      }
    })
    if(!have){
      allEdge.push({type: 'simple', from: fromNodeName, to: toNodeName, label: '', style: defstyle});
      this.setState({allNode:allNode,allEdge:allEdge,startNodeName:''});
    }
  }

  updateEdges(fromNodeName, toNodeName, toNode,that){
    let executed = 'stroke: #000000; fill: transparent';
    let defstyle = 'stroke: #ccc; fill: transparent; stroke-dasharray: 5, 5';
    const {allNode,allEdge} = that.state;
    let fromNode = allNode[fromNodeName];
    if(fromNode ==undefined){
      return [];
    }
    for(var i in allEdge){
      if(allEdge[i].from == fromNodeName && (fromNode.type != "FORK" && fromNode.type != "DECISION")){
        console.log("节点"+fromNodeName+"只能有一条线");
        return [];
      }
    }
    let style = defstyle;

    if(fromNode.type == "FORK"){
      return [{type: 'FORK', from: fromNodeName, to: toNode.ref, label: '', style: style}];
    }
    if(fromNode.type == "DECISION"){
      return [{type: 'decision', from: fromNodeName, to: toNode.ref, label: '', style: style}];
    }
    return [{type: 'simple', from: fromNodeName, to: toNode.ref, label: '', style: style}];
  }



  drawNode(v,node ,that){
    const {allNode,startNodeName,allEdge} = that.state;
    if(v !='start' && v!='final'){
      node.ref = v + new Date().getTime();
    }else{
      node.ref =  v;
    }
    if(v == 'DELETE') {
      if (startNodeName == '') {
        return;
      }
      delete allNode[startNodeName];
      let allEdgesCopy = [];
      allEdge.forEach(e => {
        if(e.from !=startNodeName && e.to != startNodeName){
          allEdgesCopy.push(e);
        }
      });
      that.setState({allNode: allNode, allEdge: allEdgesCopy, startNodeName: ''});
      return;
    }
    if(v != "start" && isEmpty(allNode)){
      alert("第一个节点选择start");
      return;
    }
    if(v != "start" && startNodeName ==''){
      alert("选择一个节点");
      return;
    }
    if(startNodeName !=''){
      let subEdges = that.updateEdges(startNodeName,v,node,that);
      if(subEdges.length == 0){
        console.log("不能增加节点");
        return ;
      }
      subEdges.forEach(e=>allEdge.push(e));
    }

    allNode[node.ref] = node;
    that.setState({allNode: allNode, allEdge: allEdge, startNodeName: ''});

  }

  render() {
    const {layout} = this.props;
    const {allNode,allEdge,startNodeName} = this.state;

    let g = new dagreD3.graphlib.Graph().setGraph({rankdir: layout});
    g.setNode("start", {
      label: "start",
      type: "start",
      shape: "circle",
      style: "",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("final", {
      label: "final",
      type: "final",
      shape: "circle",
      style: "",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("FORK", {
      label: "FORK",
      type: "FORK",
      shape: "house",
      style: "fill: #ff0",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("JOIN", {
      label: "JOIN",
      type: "JOIN",
      shape: "ellipse",
      style: "fill: #ff0",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("DECISION", {
      label: "DECISION",
      type: "DECISION",
      shape: "diamond",
      style: "fill: #ff0",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("HTTP_JSON", {
      label: "HTTP_JSON",
      type: "HTTP_JSON",
      shape: "rect",
      style: "fill:#efefef",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("LAMDA", {
      label: "LAMDA",
      type: "LAMDA",
      shape: "rect",
      style: "fill:#efefef",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });

    g.setNode("task", {
      label: "task",
      type: "task",
      shape: "rect",
      style: "",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("EVENT", {
      label: "EVENT",
      type: "EVENT",
      shape: "star",
      style: "fill: #ff0",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    g.setNode("DELETE", {
      label: "DELETE",
      type: "DELETE",
      shape: "rect",
      style: "fill: #ccc",
      labelStyle: ' font-weight:normal; font-size: 11px'
    });
    let svg = d3.select(this.svgElem);
    let inner = svg.select("g");
    inner.attr("transform", "translate(20,20)");
    this.grapher(inner, g);
    let w = g.graph().width + 50;
    let h = g.graph().height + 50;
    let p = this;

    svg.attr("width", w + "px").attr("height", h + "px");

    inner.selectAll("g.node")
      .on("mousedown",(v)=>{var node =g.node(v); this.drawNode(v,node,p)})

    return (
      <div className="ui-content">
        <svg ref={this.setSvgNode}>
          <g transform="translate(20,20)"/>
        </svg>
        <Tabs>
          <Tab eventKey={1} title="Diagram">
            <div><WorkflowMetaDraw meta={allNode} tasks={[]}
                                   allEdge={allEdge}
                                   startNodeName ={startNodeName}
                                   addInsertJoinLine={this.addInsertJoinLine}
                                   updateNodeName={this.updateStartNodeName}/></div>
          </Tab>
          <Tab eventKey={2} title="JSON">
            <div><pre>
          </pre></div>
          </Tab>
        </Tabs>
      </div>
    );
  }
};

export default connect(state => state.workflow)(WorkflowMetaAdd);
